// 版权所有2016 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build linux&&（mips | | mipsle）
// +build linux 
// +build mips mipsle 

package syscall

import "unsafe"

// /Archonsorsr2捕捉到r2被
// /runtime.GOARCH尊重的事实。系统调用约定通常为r1、r2，err:=
// Syscall（陷阱，…）。并非所有架构都在
// ABI中定义r2。参见“人工系统调用”。
const archHonorsR2 = true

const _SYS_setgroups = SYS_SETGROUPS

func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)

// sys Dup2（oldfd int，newfd int）（错误）
// sysnb EpollCreate（size int）（fd int，error）
// sys Fchown（fd int，uid int，gid int）（error error）
// sys fstatat（dirfd int，path string，stat*stat，flags int）（error）=sys fstat64 
// sys Ftruncate（fd int，length int64）（error error）=sysftruncate64abcdefg
// sysnb Geteuid（）（euid int）
// sysnb Getgid（）（gid int）
// sysnb Getuid（）（uid int）
// SYS Lchown（路径字符串，uid int，gid int）（error）
// sys Pause（）（err error）
// sys Pread（fd int，p[]字节，偏移量int64）（n int，err error）=sys PREAD64 
// sys Pwrite（fd int，p[]字节，偏移量int64）（n int，err err error）=sys PWRITE64 
// sys Select（nfd int，r*FdSet，w*FdSet，e*FdSet，timeout*Timeval）（n int，err error）=sys\U NEWSELECT 
// sys sendfile（输出int，输入int，偏移量*int64，计数int）（写入int，错误）=sys SENDFILE64 
// sys Setfsgid（gid int）（错误）
// sys Shutdown（fd int，how int）（错误）
// sys SPLITE（rfd int，roff*int64，wfd int，woff*int64，len int，flags int）（n int，错误）

// sys SyncFileRange（fd int，off int64，n int64，flags int）（错误）
// sys Truncate（路径字符串，长度int64）（错误）=SYS_TRUNCATE64 
// SYS-Ustat（dev-int，ubuf*Ustat_-t）（error）
// SYS-accept（s-int，rsa*RawSockaddrAny，addrlen*_-Socklen）（fd-int，error）
// SYS-accept4（s-int，rsa*RawSockaddrAny，addrlen*_-Socklen，flags-int）（fd-int，error）
// SYS-bind（s int，addr unsafe.Pointer，addrlenSocklen）（错误）
// sys connect（s int，addr unsafe.Pointer，addrlenSocklen）（错误）
// sysnb getgroups（n int，list*Gidt）（nn int，error）
// sys setsockopt（s int，level int，name int，val unsafe.Pointer，vallen uintpttr）（错误）
// sysnb socket（domain int，typ int，proto int）（fd int，error）
// sysnb socketpair（domain int，typ int，proto int，fd*[2]int32）（错误）
// sysnb getsockname（fd int，rsa*RawSockaddrAny，addrlen*_Socklen）（错误）
// sys recvfrom（fd int，p[]字节，flags int，from*RawSockaddrAny，from Socklen*(Socklen）（n int，错误）
// sys sendto（s int，buf[]字节，flags int，to unsafe.Pointer，addrlen_Socklen）（error error）
// sys recvmsg（s int，msg*Msghdr，flags int）（n int，error）
// sys sendmsg（s int，msg*Msghdr，flags int）（n int，error）

// sysnb tifyinit（）（fd int，error）
// sys Ioperm（from，num int，num int，on int，on int）错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误错误

// sys-utimes（路径字符串，times*[2]Timeval）（错误）

// sys-Lstat（路径字符串，stat*stat\t）（错误）=sys LSTAT64 
// sys-Fstat（fd-int，stat*stat\t）（错误）=sys FSTAT64 
// sys sys stat stat（路径字符串，stat*stat\t）（错误）=sys stat 64 

func Fstatfs(fd int, buf *Statfs_t) (err error) {
	_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
	if e != 0 {
		err = errnoErr(e)
	}
	return
}

func Statfs(path string, buf *Statfs_t) (err error) {
	p, err := BytePtrFromString(path)
	if err != nil {
		return err
	}
	_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(p)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
	if e != 0 {
		err = errnoErr(e)
	}
	return
}

func Seek(fd int, offset int64, whence int) (off int64, err error) {
	_, _, e := Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offset>>32), uintptr(offset), uintptr(unsafe.Pointer(&off)), uintptr(whence), 0)
	if e != 0 {
		err = errnoErr(e)
	}
	return
}

func setTimespec(sec, nsec int64) Timespec {
	return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
}

func setTimeval(sec, usec int64) Timeval {
	return Timeval{Sec: int32(sec), Usec: int32(usec)}
}

// sysnb pipe2（p*[2]_C_int，flags int）（error error）

func Pipe2(p []int, flags int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe2(&pp, flags)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

// sysnb pipe（）（p1 int，p2 int，error）

func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	p[0], p[1], err = pipe()
	return
}

// sys mmap2（addr uintpttr，length uintpttr，prot，flags int，fd int，pageOffset uintpttr）（xaddr uintpttr，error）

func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
	page := uintptr(offset / 4096)
	if offset != int64(page)*4096 {
		return 0, EINVAL
	}
	return mmap2(addr, length, prot, flags, fd, page)
}

const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)

type rlimit32 struct {
	Cur uint32
	Max uint32
}

// sysnb getrlimit（资源int，rlim*rlimit32）（错误）=SYS_getrlimit 

func Getrlimit(resource int, rlim *Rlimit) (err error) {
	err = prlimit(0, resource, nil, rlim)
	if err != ENOSYS {
		return err
	}

	rl := rlimit32{}
	err = getrlimit(resource, &rl)
	if err != nil {
		return
	}

	if rl.Cur == rlimInf32 {
		rlim.Cur = rlimInf64
	} else {
		rlim.Cur = uint64(rl.Cur)
	}

	if rl.Max == rlimInf32 {
		rlim.Max = rlimInf64
	} else {
		rlim.Max = uint64(rl.Max)
	}
	return
}

// sysnb setrlimit（资源int，rlim*rlimit32）（错误）=SYS_setrlimit 

func Setrlimit(resource int, rlim *Rlimit) (err error) {
	err = prlimit(0, resource, rlim, nil)
	if err != ENOSYS {
		return err
	}

	rl := rlimit32{}
	if rlim.Cur == rlimInf64 {
		rl.Cur = rlimInf32
	} else if rlim.Cur < uint64(rlimInf32) {
		rl.Cur = uint32(rlim.Cur)
	} else {
		return EINVAL
	}
	if rlim.Max == rlimInf64 {
		rl.Max = rlimInf32
	} else if rlim.Max < uint64(rlimInf32) {
		rl.Max = uint32(rlim.Max)
	} else {
		return EINVAL
	}

	return setrlimit(resource, &rl)
}

func (r *PtraceRegs) PC() uint64 { return uint64(r.Regs[64]) }

func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = uint32(pc) }

func (iov *Iovec) SetLen(length int) {
	iov.Len = uint32(length)
}

func (msghdr *Msghdr) SetControllen(length int) {
	msghdr.Controllen = uint32(length)
}

func (cmsg *Cmsghdr) SetLen(length int) {
	cmsg.Len = uint32(length)
}

func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno)
